package com.attendance.www.hr.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;

import com.attendance.www.hr.beans.AttendanceBean;
import com.attendance.www.hr.beans.AttendanceDataBean;
import com.attendance.www.hr.beans.AttendancePageBean;
import com.attendance.www.hr.beans.ReportAttendanceParam;
import com.attendance.www.hr.beans.RequestSelectBean;
import com.attendance.www.hr.beans.SchedulWeekBean;
import com.attendance.www.hr.constant.AppConstant;
import com.attendance.www.hr.dao.mapper.ApprovalRecordMapper;
import com.attendance.www.hr.dao.mapper.AttachmentMapper;
import com.attendance.www.hr.dao.mapper.AttendanceExtMapper;
import com.attendance.www.hr.dao.mapper.AttendanceMapper;
import com.attendance.www.hr.dao.mapper.DictionaryMapper;
import com.attendance.www.hr.dao.mapper.EmployeeExtMapper;
import com.attendance.www.hr.dao.mapper.EmployeeMapper;
import com.attendance.www.hr.dao.mapper.EmployeeRoleExtMapper;
import com.attendance.www.hr.dao.mapper.EmployeeRoleMapper;
import com.attendance.www.hr.dao.mapper.EmployeeSchedulMapper;
import com.attendance.www.hr.dao.mapper.EmployeeSpecialMapper;
import com.attendance.www.hr.dao.mapper.LactationExtMapper;
import com.attendance.www.hr.dao.mapper.PunchTimeMapper;
import com.attendance.www.hr.dao.mapper.RequestMapper;
import com.attendance.www.hr.dao.mapper.RetroactiveExtMapper;
import com.attendance.www.hr.dao.mapper.RetroactiveMapper;
import com.attendance.www.hr.dao.mapper.SchedulDayMapper;
import com.attendance.www.hr.dao.mapper.SchedulWeekExtMapper;
import com.attendance.www.hr.dao.mapper.SchedulWeekMapper;
import com.attendance.www.hr.dao.mapper.SpecialMapper;
import com.attendance.www.hr.entitys.ApprovalRecordExample;
import com.attendance.www.hr.entitys.Attachment;
import com.attendance.www.hr.entitys.Attendance;
import com.attendance.www.hr.entitys.AttendanceExample;
import com.attendance.www.hr.entitys.Dictionary;
import com.attendance.www.hr.entitys.DictionaryExample;
import com.attendance.www.hr.entitys.Employee;
import com.attendance.www.hr.entitys.EmployeeExample;
import com.attendance.www.hr.entitys.EmployeeRole;
import com.attendance.www.hr.entitys.EmployeeRoleExample;
import com.attendance.www.hr.entitys.EmployeeSchedul;
import com.attendance.www.hr.entitys.PunchTime;
import com.attendance.www.hr.entitys.PunchTimeExample;
import com.attendance.www.hr.entitys.Request;
import com.attendance.www.hr.entitys.RequestExample;
import com.attendance.www.hr.entitys.Retroactive;
import com.attendance.www.hr.entitys.RetroactiveExample;
import com.attendance.www.hr.entitys.SchedulDayKey;
import com.attendance.www.hr.exception.ResultFaultException;
import com.attendance.www.hr.service.IApprovalService;
import com.attendance.www.hr.service.IAttendanceService;
import com.attendance.www.hr.service.IBpmService;
import com.attendance.www.hr.service.IReportService;
import com.attendance.www.hr.utils.FactorialUtils;
import com.attendance.www.hr.utils.TimeUtils;
import com.attendance.www.hr.utils.ToolUtils;

@Service
public class AttendanceServiceImpl implements IAttendanceService {

	@Resource
	private AttendanceExtMapper attendanceExtDao;
	@Resource
	private AttachmentMapper attachmentDao;
	@Resource
	private EmployeeMapper employeeDao;
	@Resource
	private EmployeeExtMapper employeeExtDao;
	@Resource
	private RetroactiveMapper retroactiveDao;
	@Resource
	private RetroactiveExtMapper retroactiveExtDao;
	@Resource
	private ApprovalRecordMapper approvalRecordDao;
	@Resource
	private AttendanceMapper attendanceDao;
	@Resource
	private RequestMapper requestDao;
	@Resource
	private SpecialMapper specialDao;
	@Resource
	private PunchTimeMapper punchTimeDao;
	@Resource
	private EmployeeSchedulMapper employeeSchedulDao;
	@Resource
	private SchedulDayMapper schedulDayDao;
	@Resource
	private DictionaryMapper dictionaryDao;
	@Resource
	private LactationExtMapper lactationExtDao;
	@Resource
	private EmployeeSpecialMapper employeeSpecialDao;
	@Resource
	private EmployeeRoleMapper employeeRoleDao;
	@Resource
	private EmployeeRoleExtMapper employeeRoleExtDao;
	@Resource
	private IReportService reportService;
	@Resource
	private IApprovalService approvalService;
	@Resource
	private IBpmService bpmService;
	@Resource
	private SchedulWeekMapper schedulWeekDao;
	@Resource
	private SchedulWeekExtMapper schedulWeekExtDao;

	/**
	 * 分等级账户等级获取， PrivilegeGroupId=4为admin账户，可以直接查询全部
	 * PrivilegeGroupId=3为hr账户，可以查询所分配公司
	 * PrivilegeGroupId=2为审批人账户，可以查询所属下属岗位，可多岗位一起查询
	 * PrivilegeGroupId=1为员工账户，可以查询自己的考勤 可根据公司，部门，员工名称，员工级别，考勤状态，补签状态，审核状态，签到日期，签退日期
	 * 来获取员工号，中午名，英文名，签到日期，上班日期，末班签退，考勤状态，补签状态，补签状态，审批状态，补签时间，特殊考勤时间，备注
	 */
	@Override
	public AttendancePageBean getAttendanceList(AttendanceBean attendanceBean, Integer startNum, Integer pageCount,
			Integer employeeId, Boolean type) {
		AttendancePageBean attendancePageBean = new AttendancePageBean();
		List<AttendanceBean> attendanceBeanList = new ArrayList<AttendanceBean>();
		int pageTotal = 0;
		// 获取系统当前时间
		List<Integer> employeeIdList = new ArrayList<Integer>();
		if (attendanceBean.getPrivilegeGroupId() == 5) {
			if (attendanceBean.isRoleType()) {
				// 登陆员工ID，查询所属岗位，然后通过岗位查询-岗位下的员工ID
				List<Integer> roleListId = attendanceExtDao.getRolrByEmployeeId(attendanceBean, employeeId);
				if (roleListId.size() > 0) {
					//employeeIdList = attendanceExtDao.getEmployeeIdListByRoleId(attendanceBean, employeeId, roleListId);
					// 循环岗位ID获取员工ID
					for (int i = 0; i < roleListId.size(); i++) {
						employeeIdList.addAll(employeeRoleExtDao.selectEmployeeRoleGetEmployeeIdByRoleId(roleListId.get(i)));
					}
					if (employeeIdList.size() == 0) {
						attendancePageBean.setAttendanceBeanList(attendanceBeanList);
						attendancePageBean.setPageTotal(0);
						return attendancePageBean;
					}
					attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean, employeeIdList, startNum,
							pageCount, type);
					pageTotal = attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);
				}
			} else {
				employeeIdList = attendanceExtDao.getEmployeeByCorporation(attendanceBean, employeeId);
				if (employeeIdList.size() == 0) {
					attendancePageBean.setAttendanceBeanList(attendanceBeanList);
					attendancePageBean.setPageTotal(0);
					return attendancePageBean;
				}
				attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean, employeeIdList, startNum,
						pageCount, type);
				pageTotal = attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);
			}
		}
		// 判断是否为分公司HR权限
		else if (attendanceBean.getPrivilegeGroupId() == 4) {
			// 登陆员工ID，查询所属岗位，然后通过岗位查询-岗位下的员工ID
			employeeIdList = attendanceExtDao.getEmployeeByCorporation(attendanceBean, employeeId);
			if (employeeIdList.size() == 0) {
				attendancePageBean.setAttendanceBeanList(attendanceBeanList);
				attendancePageBean.setPageTotal(0);
				return attendancePageBean;
			}
			attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean, employeeIdList, startNum, pageCount,
					type);
			pageTotal = attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);
		}
		// 判断审批人
		else if (attendanceBean.getPrivilegeGroupId() == 3) {
			employeeIdList = new ArrayList<Integer>();
			EmployeeRoleExample employeeRoleExample = new EmployeeRoleExample();
			employeeRoleExample.createCriteria().andEmployeeIdEqualTo(employeeId);
			List<EmployeeRole> employeeRoleList = employeeRoleDao.selectByExample(employeeRoleExample);
			for (int i = 0; i < employeeRoleList.size(); i++) {
				employeeIdList.addAll(employeeRoleExtDao
						.selectEmployeeRoleGetEmployeeIdByRoleId(employeeRoleList.get(i).getRoleId()));
			}
			employeeIdList = FactorialUtils.filterEmployeeId(employeeIdList);
			attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean, employeeIdList, startNum, pageCount,
					type);
			pageTotal = attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);

			/**** 原版本-根据岗位ID查询员工ID集合 ****/
			/*
			 * // 登陆员工ID，查询所属岗位，然后通过岗位查询-岗位下的员工ID List<Integer> roleListId =
			 * attendanceExtDao.getRolrByEmployeeId(attendanceBean, employeeId); if
			 * (roleListId.size() > 0) { employeeIdList =
			 * attendanceExtDao.getEmployeeIdListByRoleId(attendanceBean, employeeId,
			 * roleListId); if (employeeIdList.size() == 0) {
			 * attendancePageBean.setAttendanceBeanList(attendanceBeanList);
			 * attendancePageBean.setPageTotal(0); return attendancePageBean; }
			 * attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean,
			 * employeeIdList, startNum, pageCount, type); pageTotal =
			 * attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);
			 * } else { attendanceBean.setEmployeeId(employeeId); }
			 */
			/************************************/
		}
		// 判断普通用户
		else if (attendanceBean.getPrivilegeGroupId() == 2) {
			attendanceBean.setEmployeeId(employeeId);
			attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean, employeeIdList, startNum, pageCount,
					type);
			pageTotal = attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);
		} else {
			attendanceBeanList = attendanceExtDao.getAttendanceList(attendanceBean, employeeIdList, startNum, pageCount,
					type);
			pageTotal = attendanceExtDao.getAttendanceListPageTotal(attendanceBean, employeeIdList);
		}

		// 循环遍历是否有申请信息
		for (int i = 0; i < attendanceBeanList.size(); i++) {
			AttendanceBean ab = attendanceBeanList.get(i);
			ab.setAttendanceStateType(false);
			// 是否有审批通过补签
			/*
			 * if(ab.getFlgRetroactive()>0){ ab.setAttendanceStateType(true); }
			 */
			// 是否有申请同意
			if (ab.getFlgRequest() > 0) {
				ab.setAttendanceStateType(true);
			}
			// 是否有上班补签审批中
			if (ab.getFlgStart() > 0) {
				ab.setRetroactiveStartType(true);
			} else {
				ab.setRetroactiveStartType(false);
			}
			// 是否有末班补签审批中
			if (ab.getFlgEnd() > 0) {
				ab.setRetroactiveEndType(true);
			} else {
				ab.setRetroactiveEndType(false);
			}
		}
		attendancePageBean.setAttendanceBeanList(attendanceBeanList);
		attendancePageBean.setPageTotal(pageTotal);
		return attendancePageBean;
	}

	/**
	 * 获取个人的应出勤时间，实际出勤时间，迟到，早退，旷工，补签---update_zx
	 */
	@Override
	public AttendanceDataBean getAttendanceData(AttendanceBean attendanceBean, Integer employeeId) {
		attendanceBean.setEmployeeId(employeeId);
		AttendanceDataBean attendanceData = new AttendanceDataBean();
		ReportAttendanceParam paramBean = new ReportAttendanceParam();
		paramBean.setBeginDate(attendanceBean.getAttendanceDateStart());
		paramBean.setEndDate(attendanceBean.getAttendanceDateEnd());
		List<Integer> employeeIds = new ArrayList<>();
		employeeIds.add(employeeId);
		reportService.getAbsentCount(paramBean, employeeIds);

		// 应出勤工时
		attendanceData.setShouldAttendanceTime(attendanceExtDao.getShouldTime(attendanceBean));
		// 实际出勤时长
		attendanceData.setAttendanceTime(attendanceExtDao.getActualTime(attendanceBean));
		// 加班时长
		attendanceData.setOverTime(attendanceExtDao.getOvertime(attendanceBean));
		// 迟到
		attendanceData.setLateNumber(reportService.getLateCount(paramBean, employeeIds).get(employeeId));
		// 早退
		attendanceData.setLeaveEarlyNumber(reportService.getLeaveEarlyCount(paramBean, employeeIds).get(employeeId));
		// 取得员工旷工次数
		attendanceData.setAbsenteeismNumber(reportService.getAbsentCount(paramBean, employeeIds).get(employeeId));
		// 补签
		attendanceData.setRetroactiveNumber(reportService.getRetroactiveCount(paramBean, employeeIds).get(employeeId));
		// 请假
		RequestExample requestExample = new RequestExample();
		List<Integer> requestTypeList = new ArrayList<>();
		requestTypeList.add(7);
		requestTypeList.add(8);
		requestTypeList.add(9);
		requestExample.createCriteria().andEmployeeIdEqualTo(employeeId)
				.andStartDateBetween(attendanceBean.getAttendanceDateStart(), attendanceBean.getAttendanceDateEnd())
				.andRequestTypeNotIn(requestTypeList).andApprovalStateEqualTo(2);
		List<Request> requestList = requestDao.selectByExample(requestExample);
		attendanceData.setLeaveNumber(requestList.size());
		return attendanceData;
	}

	/**
	 * 考勤信息导入
	 * 
	 * @param attachmentId
	 * @return
	 */
	@Override
	public List<String> importAttendance(Integer attachmentId) {
		List<String> successList = new ArrayList<String>();
		// 查询附件表获取路径地址
		Attachment attachment = attachmentDao.selectByPrimaryKey(attachmentId);
		// 设置文件路径
		String pathName = attachment.getUrl().replace(AppConstant.UPLOAD_RESOURCE, AppConstant.SAVE_FILE_REPOSITORY);
		File file = new File(pathName);
		Workbook work = null;
		if (file.exists()) {
			try {
				InputStream inputStream = new FileInputStream(file);
				if (pathName.matches("^.+\\.(?i)(xls)$")) {
					work = new HSSFWorkbook(inputStream);
				} else if (pathName.matches("^.+\\.(?i)(xlsx)$")) {
					work = new XSSFWorkbook(inputStream);
				}
			} catch (Exception ex) {
				throw new ResultFaultException("0_00003");
			}
		} else {
			throw new ResultFaultException("0_00003");
		}
		if (work == null) {
			throw new ResultFaultException("0_00003");
		}

		if (work != null) {
			List<String> attendanceList = addAttendance(work);
			successList.addAll(attendanceList);
		}
		return successList;
	}

	/**
	 * 增加考勤信息
	 * 
	 * @param work
	 * @return
	 */
	private List<String> addAttendance(Workbook work) {
		SimpleDateFormat dateHmFormat = new SimpleDateFormat("HH:mm");// 可以方便地修改日期格式
		// 获取系统当前时间
		Date currentDate = new Date();
		// 设置保存考勤导入日期，用于处理当天未打卡的员工记录
		Map<Date, Date> attendanceDateMap = new HashMap<Date, Date>();
		// 人员ID
		List<Integer> employeeIdList = new ArrayList<Integer>();
		// 根据当前日期，的前一个月
		Calendar cStrat = Calendar.getInstance();
		cStrat.setTime(new Date());
		cStrat.add(Calendar.MONTH, -1);
		// 根据当前日期，的后一个月
		Calendar cEnd = Calendar.getInstance();
		cEnd.setTime(new Date());
		cEnd.add(Calendar.MONTH, 1);
		// 查询员工
		List<Employee> employeeList = employeeExtDao.getEmployeeList(currentDate, currentDate);
		Map<String, Employee> employeeMap = new HashMap<String, Employee>();
		Map<Integer, Employee> employeeIdMap = new HashMap<Integer, Employee>();
		for (int ei = 0; ei < employeeList.size(); ei++) {
			employeeMap.put(employeeList.get(ei).getEmployeeNo(), employeeList.get(ei));
			employeeIdMap.put(employeeList.get(ei).getEmployeeId(), employeeList.get(ei));
		}

		// 设置提示信息
		List<String> successList = new ArrayList<String>();

		// 获取工作表的数量
		int sheetNum = work.getNumberOfSheets();
		// 遍历工作表 找出要导入的Excel表
		for (int m = 0; m < sheetNum; m++) {
			Sheet sh = work.getSheetAt(m);
			if (sh.getSheetName().equals("考勤信息")) {
				Sheet sheet = work.getSheetAt(m);
				List<String> errorMsgList = new ArrayList<String>();// 创建错误信息列表
				// 扫描Excel每行的每个单元格
				for (int i = 1; i <= sheet.getLastRowNum(); i++) {
					Attendance attendance = new Attendance();// 创建考勤对象
					StringBuilder str = new StringBuilder("第" + (i + 1) + "行");
					Row row = sheet.getRow(i);
					// 如果一整行为空则忽略此行继续遍历
					if (row == null) {
						continue;
					}
					// 遍历某一行的所有列，如果此行每列都为空则跳过继续下一行
					boolean isNull = true;
					for (int c = 0; c < row.getLastCellNum(); c++) {
						if (row.getCell(c) == null || StringUtils.isBlank(row.getCell(c).toString())) {
							continue;
						} else {
							isNull = false;
						}
					}
					if (isNull) {
						continue;
					}

					String employeeNo = null;

					// 判断第一列员工号
					if (row.getCell(0) != null && StringUtils.isNotBlank(row.getCell(0).toString())) {
						// 判断是否为数字
						if (row.getCell(0).getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
							employeeNo = new BigDecimal(row.getCell(0).getNumericCellValue()).intValue() + "";
						} else {
							employeeNo = row.getCell(0).toString();
						}
						if (employeeNo.length() <= 4) {
							employeeNo = "0" + employeeNo;
						}
						// 判断员工号是否存在-首位补0
						if (employeeMap.containsKey(employeeNo)) {
							// 设置员工ID
							attendance.setEmployeeId(employeeMap.get(employeeNo).getEmployeeId());
							boolean type = true;
							for (int l = 0; l < employeeIdList.size(); l++) {
								if (employeeIdList.get(l) == attendance.getEmployeeId()) {
									type = false;
									break;
								}
							}
							if (type) {
								employeeIdList.add(attendance.getEmployeeId());
							}
						} else {
							str.append("员工号不存在,");
						}
					} else {
						str.append("员工号不能为空,");
					}

					// 判断第二列日期
					if (row.getCell(2) != null && StringUtils.isNotBlank(row.getCell(2).toString())) {
						Date attendanceDate = new Date();
						// 判断是否为字符串或是日期类型
						SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");// 可以方便地修改日期格式
						try {
							// 判断是否为字符串
							if (row.getCell(2).getCellType() == HSSFCell.CELL_TYPE_STRING) {
								attendanceDate = dateFormat.parse(row.getCell(2).toString());
							}
							// 判断是否为日期
							else if (HSSFDateUtil.isCellDateFormatted(row.getCell(2))) {
								attendanceDate = row.getCell(2).getDateCellValue();
							}
							// 记录导入不同的日期，将用于处理未打卡的人员使用
							if (!attendanceDateMap.containsKey(attendanceDate)) {
								attendanceDateMap.put(attendanceDate, attendanceDate);
							}
							// 设置签到日期
							attendance.setAttendanceDate(attendanceDate);

						} catch (Exception e) {
							str.append("日期格式不正确,");
						}
					} else {
						str.append("日期不能为空,");
					}

					// 判断四列签到时间
					if (row.getCell(4) != null && StringUtils.isNotBlank(row.getCell(4).toString())) {
						String startTime = null;
						// 判断是否为日期类型
						if (row.getCell(4).getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
							startTime = dateHmFormat.format(row.getCell(4).getDateCellValue());
						} else {
							try {
					            // 注意格式需要与上面一致，不然会出现异常
								Date date = dateHmFormat.parse(row.getCell(4).toString());
								startTime = dateHmFormat.format(date);
					        } catch (Exception e) {
					        	str.append("签到时间格式不正确,");
					        }
						}
						// 设置原有打卡时间
						attendance.setOriginalStartTime(startTime);
						// 设置打卡时间
						attendance.setStartTime(startTime);
					} else {
						str.append("签到时间为空,");
					}

					// 判断五列签到日期
					if (row.getCell(5) != null && StringUtils.isNotBlank(row.getCell(5).toString())) {
						String endTime = null;
						// 判断是否为日期类型
						if (row.getCell(5).getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
							// 判断是否为字符串或是日期类型
							endTime = dateHmFormat.format(row.getCell(5).getDateCellValue());
						} else {
							try {
					            // 注意格式需要与上面一致，不然会出现异常
								Date date = dateHmFormat.parse(row.getCell(5).toString());
								endTime = dateHmFormat.format(date);
					        } catch (Exception e) {
					        	str.append("签退时间格式不正确,");
					        }
						}
						// 设置原有打卡时间
						attendance.setOriginalEndTime(endTime);
						// 设置打卡时间
						attendance.setEndTime(endTime);
					} else {
						str.append("签退时间为空,");
					}

					// 判断错误信息长度
					if (str.length() == new String("第" + (i + 1) + "行").length()) {
						// 查询是否日期和人员ID是否已经导入
						AttendanceExample attendanceExample = new AttendanceExample();
						attendanceExample.createCriteria().andEmployeeIdEqualTo(attendance.getEmployeeId())
								.andAttendanceDateEqualTo(attendance.getAttendanceDate());
						List<Attendance> attendanceList = attendanceDao.selectByExample(attendanceExample);
						if (attendanceList.size() > 0) {
							attendance.setAttendanceId(attendanceList.get(0).getAttendanceId());
							attendance.setIsApprovaled(attendanceList.get(0).getIsApprovaled());
							attendance.setIsRepaired(attendanceList.get(0).getIsRepaired());
							attendance.setSpecialId(attendanceList.get(0).getSpecialId());
							attendance.setDescription(attendanceList.get(0).getDescription());
							attendance.setCreateTime(attendanceList.get(0).getCreateTime());
							attendance.setUpdateTime(new Date());
							attendanceDao.updateByPrimaryKey(attendance);
						} else {
							// 保存
							AttendanceExample atExample = new AttendanceExample();
							atExample.createCriteria().andAttendanceDateEqualTo(attendance.getAttendanceDate())
									.andEmployeeIdEqualTo(attendance.getEmployeeId());
							if (attendanceDao.countByExample(atExample) <= 0) {
								attendanceDao.insertSelective(attendance);
							} else {
								attendanceDao.updateByExampleSelective(attendance, atExample);
							}
						}
					} else {
						String errorStr = str.toString().substring(0, str.toString().length() - 1);
						errorMsgList.add(errorStr);
					}
				}

				if (errorMsgList.size() > 0) {
					throw new ResultFaultException("8_00002", errorMsgList);
				}

				Date startDate = null;
				Date endDate = null;
				// 循环日期判断最大日期和最小日期
				for (Map.Entry<Date, Date> entry : attendanceDateMap.entrySet()) {
					if (startDate == null && endDate == null) {
						startDate = entry.getValue();
						endDate = entry.getValue();
					}
					if (entry.getValue().getTime() > startDate.getTime()) {
						startDate = entry.getValue();
					}
					if (entry.getValue().getTime() < endDate.getTime()) {
						endDate = entry.getValue();
					}
				}

				// 重计算
				approvalService.resetAttendance(endDate, startDate, employeeIdList);

				successList.add(0, "考勤信息导入完成。");
				return successList;
			}
		}
		throw new ResultFaultException("0_00014");
	}

	/**
	 * 生成旷工人员考勤信息
	 * 
	 * @param attendanceDateMap
	 * @param employeeIdList
	 * @param employeeSchedulList
	 * @param schedulDayList
	 * @param punchTimeList
	 * @param employeeList
	 */
	public void addNotAttendanceDate(Date date, List<Integer> employeeIdList, List<EmployeeSchedul> employeeSchedulList,
			List<SchedulDayKey> schedulDayList, List<PunchTime> punchTimeList, List<Employee> employeeList) {
		// 查询考勤信息
		AttendanceExample attendanceExample = new AttendanceExample();
		attendanceExample.createCriteria().andAttendanceDateEqualTo(date).andEmployeeIdIn(employeeIdList);
		List<Attendance> attendanceList = attendanceDao.selectByExample(attendanceExample);

		// 查询员工无规律班次
		List<SchedulWeekBean> schedulWeekBeanList = schedulWeekExtDao.getSchedulWeekDayCountByEmployeeId(employeeIdList,
				ToolUtils.dateToYearMonthStr(date), null);

		// 根据考勤导入日期生成未打卡的人员信息
		// 循环人员+日期判断排班是否旷工
		for (int i = 0; i < employeeIdList.size(); i++) {
			int employeeId = employeeIdList.get(i);
			// 判断是否离职
			List<Employee> epList = employeeList.stream().filter(s -> s.getEmployeeId().equals(employeeId))
					.collect(Collectors.toList());
			if (epList.size() > 0) {
				Employee employee = epList.get(0);
				if (employee.getEmployeeSeparatedDate() != null) {
					if (date.getTime() > employee.getEmployeeSeparatedDate().getTime()) {
						continue;
					}
				}
			}

			Attendance addAttendance = new Attendance();
			addAttendance.setEmployeeId(employeeId);
			addAttendance.setAttendanceDate(date);
			addAttendance.setAttendanceState(5);

			// 根据年月和员工ID，获取无规律班次
			List<SchedulWeekBean> dayCount = schedulWeekBeanList.stream()
					.filter(s -> s.getEmployeeId().equals(employeeId)).collect(Collectors.toList());
			if (dayCount.size() > 0) {
				List<EmployeeSchedul> list = employeeSchedulList.stream()
						.filter(s -> s.getEmployeeId().equals(employeeId) && s.getFromDate().equals(date))
						.collect(Collectors.toList());
				if (list.size() > 0) {
					// 判断是否存在考勤
					List<Attendance> aList = attendanceList.stream().filter(s -> s.getEmployeeId().equals(employeeId))
							.collect(Collectors.toList());
					if (aList.size() <= 0) {
						attendanceDao.insertSelective(addAttendance);
						continue;
					}
				}
				continue;
			}

			// 固定班次
			List<EmployeeSchedul> list = employeeSchedulList.stream().filter(s -> s.getEmployeeId().equals(employeeId))
					.collect(Collectors.toList());
			// 判断是否在区间范围内
			// 循环判断日期范围是否匹配
			for (int ei = 0; ei < list.size(); ei++) {
				EmployeeSchedul employeeSchedul = list.get(ei);
				// 验证日期是否在区间内
				if (TimeUtils.dateCalendar(date, employeeSchedul.getFromDate(), employeeSchedul.getThruDate())) {
					// 验证日期是否生成旷工
					List<Attendance> aList = attendanceList.stream().filter(s -> s.getEmployeeId().equals(employeeId))
							.collect(Collectors.toList());
					if (aList.size() <= 0) {
						// 获取班次日期
						List<SchedulDayKey> schedulDayKeyList = schedulDayList.stream()
								.filter(s -> s.getSwId().equals(employeeSchedul.getSwId()))
								.collect(Collectors.toList());
						if (schedulDayKeyList.size() > 0) {
							// 判断是否为上班日期
							List<SchedulDayKey> sdayList = schedulDayKeyList.stream()
									.filter(s -> s.getSdDate().equals(date)).collect(Collectors.toList());
							if (sdayList.size() > 0) {
								// 保存
								attendanceDao.insertSelective(addAttendance);
							}
						}
						break;
					}
				}
			}
		}
	}

	/**
	 * 生成免签人员考勤信息
	 */
	@Override
	public boolean saveEmployeeIsVisaWaiverAttendance() {
		// 获取系统日期
		Date attendanceDate = new Date();
		// 查询考勤打卡表，默认打卡信息
		PunchTimeExample punchTimeExample = new PunchTimeExample();
		punchTimeExample.createCriteria().andIsDefaultEqualTo(1);
		List<PunchTime> punchTimeList = punchTimeDao.selectByExample(punchTimeExample);
		PunchTime punchTime = null;
		if (punchTimeList.size() > 0) {
			punchTime = punchTimeList.get(0);
		}
		// 查询人员表
		EmployeeExample employeeExample = new EmployeeExample();
		employeeExample.createCriteria().andEmployeeIsSeparatedEqualTo(0).andIsVisaWaiverEqualTo(1);
		List<Employee> employeeList = employeeDao.selectByExample(employeeExample);
		for (int i = 0; i < employeeList.size(); i++) {
			Attendance attendance = new Attendance();
			attendance.setEmployeeId(employeeList.get(i).getEmployeeId());
			attendance.setAttendanceDate(attendanceDate);
			if (punchTime != null) {
				attendance.setStartTime(punchTime.getStartToTime());
				attendance.setEndTime(punchTime.getEndToTime());
			}
			attendance.setAttendanceState(1);
			attendance.setAttendenceHours(new BigDecimal(8));
			attendance.setActualHours(new BigDecimal(8));
			attendance.setLateHours(new BigDecimal(0));
			attendance.setLeaveearlyHours(new BigDecimal(0));

			AttendanceExample atExample = new AttendanceExample();
			atExample.createCriteria().andAttendanceDateEqualTo(attendance.getAttendanceDate())
					.andEmployeeIdEqualTo(attendance.getEmployeeId());
			if (attendanceDao.countByExample(atExample) <= 0) {
				attendanceDao.insertSelective(attendance);
			} else {
				attendanceDao.updateByExampleSelective(attendance, atExample);
			}
		}
		return true;
	}

	/**
	 * 判断time是否在from，to之内
	 * 
	 * @param time 指定日期
	 * @param from 开始日期
	 * @param to   结束日期
	 * @return
	 */
	public boolean dateCalendar(Date time, Date from, Date to) {
		Calendar date = Calendar.getInstance();
		date.setTime(time);
		Calendar after = Calendar.getInstance();
		after.setTime(from);
		Calendar before = Calendar.getInstance();
		before.setTime(to);
		if (date.getTime().compareTo(after.getTime()) >= 0 && date.getTime().compareTo(before.getTime()) <= 0) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 判断time是否在from之内
	 * 
	 * @param time
	 * @param from
	 * @return
	 */
	public boolean dateCalendar(Date time, Date from) {
		Calendar date = Calendar.getInstance();
		date.setTime(time);
		Calendar after = Calendar.getInstance();
		after.setTime(from);
		if (date.getTime().compareTo(after.getTime()) >= 0) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 时间比较大小
	 * 
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public boolean timeCalendar(String startTime, String endTime) {
		boolean type = false;
		DateFormat df = new SimpleDateFormat("HH:mm");// 创建日期转换对象HH:mm:ss为时分秒，年月日为yyyy-MM-dd
		try {
			Date dt1 = df.parse(startTime);// 将字符串转换为date类型
			Date dt2 = df.parse(endTime);
			if (dt1.getTime() <= dt2.getTime()) { // 比较时间大小,如果dt1大于dt2
				type = true;
			} else {
				type = false;
			}
		} catch (ParseException e) {
			type = false;
		}
		return type;
	}

	/**
	 * 判断是否是否为周末
	 * 
	 * @param cal
	 * @return
	 */
	private boolean isWeekend(Calendar cal) {
		int week = cal.get(Calendar.DAY_OF_WEEK) - 1;
		if (week == 6 || week == 0) {// 0代表周日，6代表周六
			return true;
		}
		return false;
	}

	/**
	 * 判断time是否在from，to之内
	 * 
	 * @param time 指定日期
	 * @param from 开始日期
	 * @param to   结束日期
	 * @return
	 */
	public boolean timeCalendar(String time, String from, String to) {
		boolean type = false;
		try {
			DateFormat df = new SimpleDateFormat("HH:mm");// 创建日期转换对象HH:mm:ss为时分秒，年月日为yyyy-MM-dd
			Calendar date = Calendar.getInstance();
			date.setTime(df.parse(time));
			Calendar after = Calendar.getInstance();
			after.setTime(df.parse(from));
			Calendar before = Calendar.getInstance();
			before.setTime(df.parse(to));
			if (date.getTime().compareTo(after.getTime()) >= 0 && date.getTime().compareTo(before.getTime()) <= 0) {
				type = true;
			} else {
				type = false;
			}
		} catch (ParseException e) {
			type = false;
		}
		return type;
	}

	/**
	 * 验证时间间隔
	 * 
	 * @param time
	 * @param from
	 * @param to
	 * @return
	 */
	public long minutesTimeCalendar(String from, String to) {
		long minutes = 0;
		try {
			DateFormat df = new SimpleDateFormat("HH:mm");// 创建日期转换对象HH:mm:ss为时分秒，年月日为yyyy-MM-dd
			Calendar after = Calendar.getInstance();
			after.setTime(df.parse(from));
			Calendar before = Calendar.getInstance();
			before.setTime(df.parse(to));
			minutes = (after.getTime().getTime() - before.getTime().getTime()) / (1000 * 60);
		} catch (ParseException e) {
			minutes = 0;
		}
		return minutes;
	}

	/**
	 * 返回分钟数据
	 * 
	 * @param from
	 * @return
	 */
	public long minutesTimeCalendar(String from) {
		long minutes = 0;
		try {
			DateFormat df = new SimpleDateFormat("HH:mm");// 创建日期转换对象HH:mm:ss为时分秒，年月日为yyyy-MM-dd
			Calendar after = Calendar.getInstance();
			after.setTime(df.parse(from));
			minutes = (after.getTime().getTime()) / (1000 * 60);
		} catch (ParseException e) {
			minutes = 0;
		}
		return minutes;
	}

	/**
	 * 获取人员考勤数据次数
	 * 
	 * @param emploueeId
	 * @param date
	 * @return
	 */
	@Override
	public Integer getAttendanceCount(Integer employeeId, Date date) {
		AttendanceExample attendanceExample = new AttendanceExample();
		attendanceExample.or().andEmployeeIdEqualTo(employeeId).andAttendanceDateEqualTo(date).andEndTimeIsNotNull();
		attendanceExample.or().andEmployeeIdEqualTo(employeeId).andAttendanceDateEqualTo(date).andStartTimeIsNotNull();
		return attendanceDao.countByExample(attendanceExample);
	}

	/**
	 * 根据考勤Id来获取当前日期的所有申请
	 * 
	 * @param AttendanceId
	 * @return
	 */
	@Override
	public List<RequestSelectBean> getAttendanceRight(AttendanceBean attendanceBean) {
		List<String> dicClsList = new ArrayList<String>();
		dicClsList.add("4");
		dicClsList.add("10");

		// 申请状态
		Map<Integer, String> requestMap = new HashMap<Integer, String>();
		// 审批状态
		Map<Integer, String> approvalMap = new HashMap<Integer, String>();

		// 设置返回列表
		List<RequestSelectBean> requestSelectBeanList = new ArrayList<RequestSelectBean>();
		DictionaryExample dictionaryExample = new DictionaryExample();
		dictionaryExample.createCriteria().andDicClsIn(dicClsList);
		dictionaryExample.setOrderByClause("dic_cls asc,dic_cd asc");
		List<Dictionary> dictionaryList = dictionaryDao.selectByExample(dictionaryExample);
		for (int i = 0; i < dictionaryList.size(); i++) {
			if (dictionaryList.get(i).getDicCls().equals("4")) {
				requestMap.put(Integer.valueOf(dictionaryList.get(i).getDicCd()), dictionaryList.get(i).getDicName());
			} else {
				approvalMap.put(Integer.valueOf(dictionaryList.get(i).getDicCd()), dictionaryList.get(i).getDicName());
			}
		}

		EmployeeExample employeeExample = new EmployeeExample();
		employeeExample.createCriteria().andEmployeeNoEqualTo(attendanceBean.getEmployeeNo());
		List<Employee> employeeList = employeeDao.selectByExample(employeeExample);

		// 获取Request请求类型
		RequestExample requestExample = new RequestExample();
		requestExample.createCriteria().andEmployeeIdEqualTo(employeeList.get(0).getEmployeeId())
				.andStartDateLessThanOrEqualTo(attendanceBean.getAttendanceDate())
				.andEndDateGreaterThanOrEqualTo(attendanceBean.getAttendanceDate()).andApprovalStateNotEqualTo(0);// 未提交的不显示
		List<Request> requestList = requestDao.selectByExample(requestExample);
		for (int i = 0; i < requestList.size(); i++) {
			RequestSelectBean requestSelectBean = new RequestSelectBean();
			requestSelectBean.setStartDate(requestList.get(i).getStartDate());
			requestSelectBean.setStartTime(requestList.get(i).getStartTime());
			requestSelectBean.setStartToTime(requestList.get(i).getStartToTime());
			requestSelectBean.setEndDate(requestList.get(i).getEndDate());
			requestSelectBean.setEndTime(requestList.get(i).getEndTime());
			requestSelectBean.setRequestType(requestMap.get(requestList.get(i).getRequestType()));
			// 婚假
			if(requestList.get(i).getRequestType() == 3) {
				requestSelectBean.setMarryDate(requestList.get(i).getMarryDate());
			}
			requestSelectBean.setRequestDate(requestList.get(i).getRequestDate());
			requestSelectBean.setRequestId(requestList.get(i).getRequestId());
			requestSelectBean.setApprovalState(requestList.get(i).getApprovalState());
			requestSelectBean.setApprovalStateName(approvalMap.get(requestList.get(i).getApprovalState()));
			requestSelectBeanList.add(requestSelectBean);
		}
		return requestSelectBeanList;
	}

	/**
	 * 根据考勤Id来撤回补签信息
	 * 
	 * @param attendanceId
	 * @param type
	 * @return
	 */
	@Override
	public boolean retractAttednance(Integer attendanceId, Integer type) {
		Retroactive retroactive = null;
		// 查询考勤信息，是否已经
		RetroactiveExample retroactiveExample = new RetroactiveExample();
		retroactiveExample.setOrderByClause("create_time desc");
		List<Retroactive> retroactivesList = new ArrayList<Retroactive>();
		ApprovalRecordExample approvalRecordExample = new ApprovalRecordExample();
		if (type == 0) {
			retroactiveExample.createCriteria().andAttendanceIdEqualTo(attendanceId).andEndTimeIsNull();
			retroactivesList = retroactiveDao.selectByExample(retroactiveExample);
		} else {
			retroactiveExample.createCriteria().andAttendanceIdEqualTo(attendanceId).andStartTimeIsNull();
			retroactivesList = retroactiveDao.selectByExample(retroactiveExample);
		}
		// 判断是否已经审批过
		if (retroactivesList.size() > 0) {
			retroactive = retroactivesList.get(0);
			if (retroactivesList.get(0).getApprovalState() == 2 || retroactivesList.get(0).getApprovalState() == 3) {
				throw new ResultFaultException("4_00019");
			}
		}

		// 请求BPM系统撤回
		if (bpmService.revokeBPM(null, retroactive, retroactive.getEmployeeId(), "hr003")) {
			for (int i = 0; i < retroactivesList.size(); i++) {
				int retroactiveId = retroactivesList.get(i).getRetroactiveId();
				approvalRecordExample.createCriteria().andRetroactiveIdEqualTo(retroactiveId);
				retroactiveDao.deleteByPrimaryKey(retroactiveId);
				approvalRecordDao.deleteByExample(approvalRecordExample);
			}

			RetroactiveExample retroactiveExample2 = new RetroactiveExample();
			retroactiveExample2.createCriteria().andAttendanceIdEqualTo(attendanceId);
			retroactivesList = retroactiveDao.selectByExample(retroactiveExample2);
			Attendance attendance = new Attendance();
			attendance.setAttendanceId(attendanceId);
			if (retroactivesList.size() > 0) {
				Integer approvalState = retroactivesList.get(0).getApprovalState();
				attendanceDao.selectByPrimaryKey(attendanceId).setIsRepaired(approvalState);
				attendance.setIsApprovaled(approvalState);
				attendance.setIsRepaired(approvalState);
			} else {
				attendance.setIsApprovaled(0);
				attendance.setIsRepaired(0);
			}
			attendanceDao.updateByPrimaryKeySelective(attendance);
		}
		return true;
	}

	/**
	 * 获取原始打卡时by日期
	 */
	@Override
	public AttendanceBean getAttendanceTimeByDate(AttendanceBean attendanceBean) {
		// 查询考勤信息
		AttendanceExample attendanceExample = new AttendanceExample();
		attendanceExample.createCriteria().andAttendanceDateEqualTo(attendanceBean.getAttendanceDate())
				.andEmployeeIdEqualTo(attendanceBean.getEmployeeId());
		List<Attendance> attList = attendanceDao.selectByExample(attendanceExample);
		// 查询字典表-考勤状态
		DictionaryExample dictionaryExample = new DictionaryExample();
		dictionaryExample.createCriteria().andDicClsEqualTo("1");
		List<Dictionary> dictionaryList = dictionaryDao.selectByExample(dictionaryExample);
		if (attList.size() > 0) {
			attendanceBean.setAttendanceId(attList.get(0).getAttendanceId());
			attendanceBean.setOriginalStartTime(attList.get(0).getOriginalStartTime());
			attendanceBean.setOriginalEndTime(attList.get(0).getOriginalEndTime());
			attendanceBean.setAttendanceState(attList.get(0).getAttendanceState());
			if (attList.get(0).getAttendanceState() != null) {
				List<Dictionary> dList = dictionaryList.stream()
						.filter(s -> s.getDicCd().equals(attList.get(0).getAttendanceState().toString()))
						.collect(Collectors.toList());
				if (dList.size() > 0) {
					attendanceBean.setAttendanceStateName(dList.get(0).getDicName());
				}
			}
		}
		return attendanceBean;
	}

}
